﻿using System;
using System.Collections.Generic;
//using System.Drawing;
using System.Drawing;
using System.Drawing.Imaging;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Hardcodet.Wpf.TaskbarNotification.Interop;
using MahApps.Metro.Controls;
using monitor_2_DBwork;
using monitor_server_2_WPF;
//using monitor_server_2_WPF.ControlTabs;
using monitor_server_2_WPF.CustomControls;
using monitor_server_2_WPF.MainWindowControls;
using monitor_server_2_WPF.Windows;
using Color = System.Windows.Media.Color;
using Image = System.Windows.Controls.Image;
using ServerLib;
using Hardcodet.Wpf.TaskbarNotification;

namespace monitor_server_2_WPF
{
    /// <summary>
    /// Логика взаимодействия для MainWindow.xaml
    /// </summary>
    public partial class MainWindow
    {
        public delegate void HidingDelegate();

        private delegate string ServerStartDelegate();

        private delegate void SendBoolDelegate(bool a);
        private delegate void SendStringDelegate(string a);

        public delegate void UserEntriesChangedDelegate(string a);
        public delegate void LogEntriesChangedDelegate(string a, string b);

        private LogWindow _logWindow;
        private TrayControl _tray;
        private TaskbarIcon _trayIcon;

        //private CloseSplashDelegate _closeSplash;
        private HidingDelegate _hide;
        public event HidingDelegate HideEvent;
        private object _lastOpenedConfig;

        protected virtual void OnHideEvent()
        {
            var handler = HideEvent;
            if (handler != null) handler();
        }

        private ObserveTabControl _observeTab;
        private ControlTabControl _controlTab;
        private AccessListTabControl _accessListTab;
        private TrustedAddressListTabControl _trustedAddressListTab;
        private DeviceListTabControl _deviceListTab;

        private MenuItem _servstart;

        private UnautorizedPage _unautorizedPage;

        private bool _isAuthorized = false;
        private readonly TextBlock _autorizeText;// = new TextBlock { Text = Res.Rm.GetString("Authorization"), Margin = new Thickness(3, 0, 3, 0) };
        private readonly TextBlock _unAutorizeText;// = new TextBlock { Text = Res.Rm.GetString("Exit"), Margin = new Thickness(3, 0, 3, 0) };

        //public MainWindow(CloseSplashDelegate d)
        public MainWindow()
        {
            

            Thread.CurrentThread.CurrentUICulture = new CultureInfo("ru-RU");
            //Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-US");
            _autorizeText = new TextBlock {Text = Res.Rm.GetString("Authorization"), Margin = new Thickness(3, 0, 3, 0)};
            _unAutorizeText = new TextBlock {Text = Res.Rm.GetString("Exit"), Margin = new Thickness(3, 0, 3, 0)};
            AppDomain.CurrentDomain.UnhandledException += dom_UnhandledException;
            InitializeComponent();
            Background = new SolidColorBrush(Res.LighBlack);
            Title = Res.Rm.GetString("MonitoringSystem");
            //Observe window loading
            LogEntriesChangedDelegate logs = ChangeNewLogEntries;
            UserEntriesChangedDelegate users = ChangeUsersOnlineAmount;
            LastLogSaveTimeValue.Text = "N/A";
            Server.SaveLogsComplete += () => Dispatcher.Invoke(new Action(() =>
            {
                LastLogSaveTimeValue.Text = DateTime.Now.ToString("t");
            }));
            Server.BizssControlComplete += () => Dispatcher.Invoke(new Action(() =>
            {
                BizssCompleteTimeValue.Text = DateTime.Now.ToString("t");
            }));
            _observeTab = new ObserveTabControl(logs, users);
            UseLayoutRounding = true;
            //var chk = DBwork.CheckConnection();
            //_deviceListTab = new DeviceListTabControl();
            try
            {
                _deviceListTab = new DeviceListTabControl();
            }
            catch(Exception ex)
            {
                MessageBox.Show(ex.Message + Environment.NewLine + Res.Rm.GetString("ProgramWillBeClosed") + '.', Res.Rm.GetString("Warning"));
                Application.Current.Shutdown();
            }
            
        }

        static void dom_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            MessageBox.Show(e.ExceptionObject.ToString(), @"Unexpected error", MessageBoxButton.OK,
                            MessageBoxImage.Error);
            Server.WriteToLog(e.ExceptionObject.ToString(), ServerCategories.SystemError);
        }
        private void MainWindow1_Loaded(object sender, RoutedEventArgs e)
        {

           
        }

        void InitWindow()
        {
            try
            {

                _unautorizedPage = new UnautorizedPage();
                //MainWindow icon
                Icon = Res.GetBitMapFromPng("main_station_32");

                //Status panel
                StatusPanel.Background = new SolidColorBrush(Res.NiceBlue);
                UsersOnlineLabel.Text = Res.Rm.GetString("UsersOnline") + ":";
                UsersOnlinevalue.Text = "0";

                NewLogEntriesLabel.Text = Res.Rm.GetString("NewLogEntries") + ":";
                NewLogEntriesValue.Text = "0";

                AccessLabel.Text = Res.Rm.GetString("UnautorizedAccess");
                AutorizeButton.Content = _autorizeText;

                UserNameLabel.Text = string.Empty;

                LastLogSaveTimeLabel.Text = Res.Rm.GetString("LastLogSaveTimeLabel") + ":";
                BizssCompleteTimeLabel.Text = Res.Rm.GetString("LastBizssCompleteTimeLabel") + ":";

                //Menu
                //Menu item
                var m = new MenuItem();
                m.Header = Res.Rm.GetString("Menu");
                var mi = new MenuItem();
                var dp = new DockPanel();
                var image = new Image { Source = Res.GetBitMapFromPng("exit_16"), Width = 16, Height = 16 };
                var t = new TextBlock();
                t.Inlines.Add(Res.Rm.GetString("Exit"));
                t.Foreground = new SolidColorBrush(Colors.White);
                dp.Children.Add(image);
                dp.Children.Add(t);
                mi.Header = dp;
                mi.Click += (o, args) => Application.Current.Shutdown();
                m.Items.Add(mi);
                //var refresh = new MenuItem();
                //refresh.Command = new RoutedCommand();
                Menu1.Items.Add(m);
                //Statistics item
                var stat = new MenuItem();
                stat.Header = Res.Rm.GetString("Statistics");
                stat.Click += StatOnClick;
                Menu1.Items.Add(stat);
                //Server Start item
                _servstart = new MenuItem();
                _servstart.Header = Res.Rm.GetString("StartServer");
                _servstart.Click += servstart_Click;
                Menu1.Items.Add(_servstart);

                MainGrid.Background = new SolidColorBrush(Res.LighBlack);

                //Status expander
                var exp1 = MainWindowExpander.Create(Res.Rm.GetString("ServerState"), "gnome_monitor");
                MainWindowExpander.AddItem(ref exp1, Res.Rm.GetString("Observation"), ControlOption_Selected);
                //MainWindowExpander.AddItem(ref exp1, Res.Rm.GetString("Statistics"));
                MainWindowExpander.AddItem(ref exp1, Res.Rm.GetString("Control"), ControlOption_Selected);
                MainWindowExpander.AddExpanderOnPanel(ref CategoriesList, exp1);

                //Config expander
                var exp2 = MainWindowExpander.Create(Res.Rm.GetString("Config"), "config_32");
                MainWindowExpander.AddItem(ref exp2, Res.Rm.GetString("AccessList"), ControlOption_Selected);
                MainWindowExpander.AddItem(ref exp2, Res.Rm.GetString("DeviceList"), ControlOption_Selected);
                MainWindowExpander.AddItem(ref exp2, Res.Rm.GetString("TrustedAddressesList"), ControlOption_Selected);
                MainWindowExpander.AddExpanderOnPanel(ref CategoriesList, exp2);

                //Tray
                _tray = new TrayControl();
                _tray.SetStatus(TrayControl.Status.Ok);
                _trayIcon = new TaskbarIcon();
                _trayIcon.TrayToolTip = _tray;
                _trayIcon.ToolTipText = Res.Rm.GetString("MonitoringSystem");
                _trayIcon.TrayMouseDoubleClick += (sender, args) =>
                {
                    (sender as TaskbarIcon).Visibility = Visibility.Collapsed;
                    Show();
                    WindowState = WindowState.Normal;
                    Activate();
                    if (Stpanel1.Children.Count > 0 && Stpanel1.Children[0].GetType() == typeof(ObserveTabControl))
                    {
                        _observeTab.IsTabVisible = true;
                        _observeTab.Reset();
                    }
                    
                };
                _trayIcon.Visibility = Visibility.Collapsed;
                var dimg = (Icon)Res.Rm.GetObject("main_station_64");
                _trayIcon.Icon = new Icon(dimg, 32, 32);

            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString(), @"Unexpected error", MessageBoxButton.OK,
                               MessageBoxImage.Error);
                Application.Current.Shutdown();

                //throw;
            }
        }

        private void StatOnClick(object sender, RoutedEventArgs routedEventArgs)
        {
            if(_logWindow == null || _logWindow.IsClosed)
                _logWindow = new LogWindow();
            _logWindow.ShowUp();
        }

        public void ChangeNewLogEntries(string newAmount, string category)
        {
            ServerCategories cat;
            if (Enum.TryParse(category, true, out cat))
            {
                if (cat == ServerCategories.Warning)
                {
                    StatusPanel.Background = new SolidColorBrush(Res.WarningOrange);
                    _tray.SetStatus(TrayControl.Status.Alarm);
                }
                if (cat == ServerCategories.SystemError)
                {
                    StatusPanel.Background = new SolidColorBrush(Colors.Red);
                    _tray.SetStatus(TrayControl.Status.Error);
                }
            }
            if (category.Equals("reset"))
            {
                StatusPanel.Background = new SolidColorBrush(Res.NiceBlue);
                _tray.SetStatus(TrayControl.Status.Ok);
            }
            //NewLogEntriesValue.Foreground = new SolidColorBrush(Colors.White);
            int a;
            if (int.TryParse(newAmount, out a))
            {
                NewLogEntriesValue.Text = newAmount;
                _tray.SetUnreadMessages(newAmount);
            }
        }

        public void ChangeUsersOnlineAmount(string newAmount)
        {
            int a;
            if (int.TryParse(newAmount, out a))
            {
                UsersOnlinevalue.Text = newAmount;
                _tray.SetUsers(newAmount);
            }
        }

        private void ChangeServStartButtonHeader(string newHeader)
        {
            _servstart.Header = newHeader;
        }

        private void ChangeServStartButtonState(bool newState)
        {
            _servstart.IsEnabled = newState;
        }

        void servstart_Click(object sender, RoutedEventArgs e)
        {
            _servstart.IsEnabled = false;
            if (_servstart.Header.ToString() == Res.Rm.GetString("StartServer"))
            {
                var sd = new ServerStartDelegate(ServerStart);
                sd.BeginInvoke(ServerStartCallback, sd);
            }
            else
            {
                var sStop = new ServerStartDelegate(ServerStop);
                sStop.BeginInvoke(ServerStopCallback, sStop);
            }
        }
        
        private void ServerStartCallback(IAsyncResult iar)
        {
            var ar = (ServerStartDelegate)iar.AsyncState;
            var res = ar.EndInvoke(iar);
            if (res != "ok")
            {
                MessageBox.Show(res.Substring(4), Res.Rm.GetString("Error"), MessageBoxButton.OK, MessageBoxImage.Stop);
            }
            else
            {
                SendStringDelegate sd = ChangeServStartButtonHeader;
                Dispatcher.Invoke(sd, new object[] {Res.Rm.GetString("StopServer")});
                Dispatcher.Invoke(new Action(() => _tray.SetServerState(true)));
            }
            SendBoolDelegate bd = ChangeServStartButtonState;
            Dispatcher.Invoke(bd, new object[] {true});
        }

        private string ServerStart()
        {
            return Server.ServerStart(null);
        }

        private void ServerStopCallback(IAsyncResult iar)
        {
            var ar = (ServerStartDelegate)iar.AsyncState;
            var res = ar.EndInvoke(iar);
            if (res != "ok")
            {
                MessageBox.Show(res.Substring(4), Res.Rm.GetString("Error"), MessageBoxButton.OK, MessageBoxImage.Stop);
            }
            else
            {
                SendStringDelegate s = ChangeServStartButtonHeader;
                Dispatcher.Invoke(s, new object[]{Res.Rm.GetString("StartServer")});
                Dispatcher.Invoke(new Action(() => _tray.SetServerState(false)));
            }
            SendBoolDelegate bd = ChangeServStartButtonState;
            Dispatcher.Invoke(bd, new object[] { true });
        }

        private string ServerStop()
        {
            return Server.ServerStop();
        }

        //Обработчик выбора одного из пунктов экспандеров
        private void ControlOption_Selected(object sender, RoutedEventArgs routedEventArgs)
        {
            Stpanel1.Children.Clear();

            OnHideEvent();
            if (_hide != null)
            {
                HideEvent -= _hide;
            }

            Res.IControlForMainWindow tab = _observeTab;

            //Список доверенных адресов
            if (((sender as ListViewItem).Content as TextBlock).Text == Res.Rm.GetString("TrustedAddressesList"))
            {
                if (_trustedAddressListTab == null)
                    _trustedAddressListTab = new TrustedAddressListTabControl();
                tab = _trustedAddressListTab;
            } else

            //Список пользователей
            if (((sender as ListViewItem).Content as TextBlock).Text == Res.Rm.GetString("AccessList"))
            {
                if (_accessListTab == null)
                    _accessListTab = new AccessListTabControl();
                tab = _accessListTab;
            } else

            //Наблюдение
            if (((sender as ListViewItem).Content as TextBlock).Text == Res.Rm.GetString("Observation"))
            {
                if (_observeTab == null)
                {
                    LogEntriesChangedDelegate logs = ChangeNewLogEntries;
                    UserEntriesChangedDelegate users = ChangeUsersOnlineAmount;
                    _observeTab = new ObserveTabControl(logs, users);
                }
                    
                tab = _observeTab;
            } else

            //Управление
            if (((sender as ListViewItem).Content as TextBlock).Text == Res.Rm.GetString("Control"))
            {
                if (_controlTab == null)
                    _controlTab = new ControlTabControl();
                _controlTab.Background = Background;
                tab = _controlTab;
            }

            //Список утройств
            if (((sender as ListViewItem).Content as TextBlock).Text == Res.Rm.GetString("DeviceList"))
            {
                if(_deviceListTab == null)
                    _deviceListTab = new DeviceListTabControl();
                tab = _deviceListTab;
            }

            _lastOpenedConfig = tab;

            if (!Equals(tab, _observeTab) && !_isAuthorized)
            {
                Stpanel1.Children.Add(_unautorizedPage);
                return;
            }

            Stpanel1.Children.Add(tab.GetControl(out _hide));

            HideEvent += _hide;
        }

        //Кнопка авторизации
        private void AutorizeButton_Click(object sender, RoutedEventArgs e)
        {
            if (!_isAuthorized)
            {
                //Авторизация
                var l = new LoginWindow(s =>
                {
                    UserNameLabel.Text = Res.Rm.GetString("User") + ':';
                    AccessLabel.Text = s;
                });
                l.Owner = this;
                var chk = l.ShowDialog();
                if (chk != true)
                    return;
                _isAuthorized = true;
                if (_lastOpenedConfig != null && _lastOpenedConfig.GetType() != typeof(ObserveTabControl))
                {
                    Stpanel1.Children.Add((_lastOpenedConfig as Res.IControlForMainWindow).GetControl(out _hide));
                    HideEvent += _hide;
                }
                (sender as Button).Content = _unAutorizeText;
            }
            else
            {
                //Выход из системы
                if (_lastOpenedConfig != null && _lastOpenedConfig.GetType() != typeof(ObserveTabControl))
                {
                    if(_hide != null)
                        _hide();
                    Stpanel1.Children.Clear();
                    Stpanel1.Children.Add(_unautorizedPage);
                }

                _isAuthorized = false;
                UserNameLabel.Text = string.Empty;
                AccessLabel.Text = Res.Rm.GetString("UnautorizedAccess");
                (sender as Button).Content = _autorizeText;
            }
        }


        private void MainWindow_OnClosed(object sender, EventArgs e)
        {
            Application.Current.Shutdown();
        }

        private void MainWindow_OnInitialized(object sender, EventArgs e)
        {
            InitWindow();
        }



        private void MainWindow_OnStateChanged(object sender, EventArgs e)
        {
            if ((sender as MetroWindow).WindowState == WindowState.Minimized)
            {
                _trayIcon.Visibility = Visibility.Visible;
                Hide();
                if (Stpanel1.Children.Count > 0 && Stpanel1.Children[0].GetType() == typeof(ObserveTabControl))
                {
                    _observeTab.IsTabVisible = false;
                }
            }
        }
    }
    public delegate void VoidStringDelegate(string a);
}
